#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from multiprocessing import Process
from threading import Thread
import os
import socket
import time
import logging
import threading
import random
import unittest
import errno

from sqlalchemy import Column
from sqlalchemy import Integer, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()


class RequestMatcher(Thread):
    def __init__(self, stock=None):
        Thread.__init__(self)
        self.stock = stock
        self.stopped = True

    def run(self):
        while not self.stopped:
            self.scan()
        pass

    def scan(self): 
        buy_queue = self.stock.get_buy_queue()
        sell_queue = self.stock.get_sell_queue()
        if buy_queue is None or sell_queue is None:
            return
        for i in range(len(buy_queue)):
            buy_request = buy_queue[i]
            for j in range(len(sell_queue)):
                sel_request = sell_queue[j]
                if buy_request.match(sell_request):
                    return True
        pass

    def stop(self):
        self.stopped = True

    def match(self):
        return False


class Stock(Base):
    __tablename__ = "stock"

    code = Column(String, primary_key=True)
    name = Column(String, unique=True)
    quantity = Column(Integer)
    price = Column(Integer)
    
    TRADE_STATE_A = 'TRADE_ACCEPTED'
    TRADE_STATE_S = 'TRADE_SUCCESSED'
    TRADE_STATE_W = 'TRADE_WAITING'
    TRADE_STATE_F = 'TRADE_FAILED'

    def __init__(self, code, name, price=0, quantity=int(INIT_AMOUNT)):
        self.code = code
        self.name = name
        self.price = price
        self.quantity = quantity

        self.buy_queue = []
        self.sell_queue = []

        self.request_matcher = RequestMatcher(self)
        self.request_matcher.run()

        return

    def __str__(self):
        return '%s-%d-%d' % (self.name, self.price, self.quantity)

    def __repr__(self):
        return "%s<%s-%d-%d>" % (self.__class__.__name__, self.name, self.price,
               self.quantity)

    def request_enqueu(self, request=TradeRequest()):
        if request.typ == "sell":
            self.sell_queue.append(request)
        elif request.typ == "buy":
            self.buy_queue.append(request)
        return

    def match(self):
        ''' Traverse buy_queue and sell_queue trying to match selling and buying 
        requets to get a success trade.
        '''
        for breq in self.buy_queue:
            for sreq in self.buy_queue:
                if breq.match(sreq):
                    try:
                        self.buy_queue.remove(breq)
                        self.sell_queue.remove(sreq)
                    except ValueError, e:
                        pass
                    self.curr_price = breq.price
                    self.quantity -= int(breq.quantity)
                    return True
        return False

    def trade(self, request=TradeRequest()):
        """Try trading, return trading result.
        """
        state = TRADE_STATE_W
        try:
            stock = self.stock_pool[request.name]
        except KeyError, e:
            state = TRADE_STATE_F
            return state

        stock.request_enqueu(request)
        if not stock.match():       # If a successful match doesn't occur,
            state = TRADE_STATE_W   # waiting
        else:
            state = TRADE_STATE_S

        return state


def set_db(db_new):
    global db

    db = db_new

    return True

db = "sqlite:///:memory:"
engine = create_engine(db, echo=False)
session = sessionmaker(bind=engine)

stock = Stock()
session.add(stock)
session.query(Stock).filter_by(code="").first()
session.commit()

if __name__ == "__main__":
    unittest.main()

